<?php

namespace app\index\service;

use app\common\model\Trade;
use app\index\model\UM as UM;
use app\index\service\payments\CardPaymentService;
use app\index\service\payments\CoinPaymentService;
use app\index\traits\PaymentProxyTrait;
use ary\Ary;
use think\exception\ValidateException;
use think\facade\Config;

/**
 * Class SourcePhoneService
 * @package app\index\service
 */
class SourcePhoneService
{
    use PaymentProxyTrait;

    /**
     * 创建或查询案源订单,返回绑定的虚拟号码
     * @param UM $user
     * @param $sourceId
     * @param array $params
     */
    public function bindAxbPhone(UM $user, $sourceId, array $params)
    {
        $companyId = $user->companyId;
        $userPersonnelId = $user->userPersonnelId;
        $memberId = $user->id;
        $memberName = $user->showName;

        $isAllin = $params['isAllin'] ?? '0';
        $phone = $params['phone'] ?? $user->axbPhone;

        if (is_blank($sourceId)) {
            throw new ValidateException('请选择一个案源');
        }

        $data = [
            'source_id' => $sourceId,
            'user_id' => $memberId,
            'user_name' => $memberName,
            'user_mobile' => $phone,
            'callbackurl' => Config::get('axb.callbackurl', '')
        ];

        $proxyCoin = false;

        // 员工
        if (is_id($userPersonnelId)) {

            // 检查是否存在代付公司，并且代付余额充足
            $proxyCoin = $this->checkProxyQuota($memberId, $companyId, $userPersonnelId, PAYMENT_COIN);
        }

        // 不能代付时检查是否可以自己支付
        if (!$proxyCoin) {

            // 检查用户的通信币账户是否可用
            if (!$this->getCoinPaymentService()->isEnableTransfer($memberId)) {
                throw new ValidateException('您的通信币账户暂时不可用，请联系管理员');
            }

            // 查询通信币余额是否大于0
            $coin = $this->getCoinPaymentService()->getBalance($memberId);
            if ($coin <= 0) {
                throw new ValidateException('您的通信币余额不足，请充值后继续操作');
            }
        }


        // 是否已经购买过了
        $trade = $this->queryTrade($sourceId, $memberId);

        if (!$trade) {

            // 查询案源信息
            $response = $this->getAry()->getSourceDetail(['source_id' => $sourceId]);
            $decodeContents = $response->getDecodeContentsOrThrow('该案源已下架', true);

            $source = $decodeContents['data'] ?? [];

            $unitPrice = $source['unit_price'];
            $allinPrice = $source['allin_price'];

            // 应付价格
            $amount = $isAllin == '1' ? $allinPrice : $unitPrice;

            $proxyCard = false;

            // 员工
            if (is_id($userPersonnelId)) {

                // 检查是否存在代付公司，并且代付余额充足
                $proxyCard = $this->checkProxyQuota($memberId, $companyId, $userPersonnelId, PAYMENT_CARD);
            }

            // 不能代付时检查是否可以自己支付
            if (!$proxyCard) {

                // 检查用户的获客卡账户是否可用
                if (!$this->getCardPaymentService()->isEnableTransfer($memberId)) {
                    throw new ValidateException('您的获客卡账户暂时不可用，请联系管理员');
                }

                // 查询获客卡余额是否足够，不足直接说获客卡余额不足，请充值后操作
                $balance = $this->getCardPaymentService()->getBalance($memberId);
                if ($balance < $amount) {
                    throw new ValidateException('您的获客卡余额不足，请充值后继续操作');
                }
            }

            $data['is_allin'] = $isAllin;
            $data['unit_price'] = $unitPrice;
            $data['allin_price'] = $allinPrice;
        }

        $axbPhone = $this->bindPhone($data);

        return [
            'axbPhone' => $axbPhone,
        ];
    }

    // 案如云-绑定号码
    private function bindPhone($params)
    {

        $response = $this->getAry()->bindSourcePhone($params);
        $decodeContents = $response->getDecodeContentsOrThrow('获取号码失败');

        $axbPhone = $decodeContents['data']['telX'] ?? null;
        if (is_blank($axbPhone)) {
            throw new ValidateException('获取号码失败.');
        }

        return $axbPhone;
    }

    private function queryTrade($sourceId, $memberId): ?Trade
    {
        return Trade::where('sourceId', $sourceId)
            ->where('memberId', $memberId)
            ->where('tradeType', TRADE_SOURCE)
            ->where('payStatus', Trade::PAID)
            ->whereIn('refundStatus', [Trade::NOTREFUND, Trade::REFUNDING, Trade::REFUND_FAILED])
            ->field(true)
            ->find();
    }

    private function getCardPaymentService(): CardPaymentService
    {
        return app(CardPaymentService::class);
    }

    private function getCoinPaymentService(): CoinPaymentService
    {
        return app(CoinPaymentService::class);
    }

    private function getAry(): Ary
    {
        return app(Ary::class);
    }
}
